package com.linkkap.feishu.api.servlet;

import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class LoggableDispatcherServlet extends DispatcherServlet {

	private static final Logger LOGGER = LoggerFactory.getLogger("HttpLogger");

	private static final ObjectMapper MAPPER = new ObjectMapper();

	@Override

	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

		ContentCachingRequestWrapper requestWrapper  = new ContentCachingRequestWrapper(request);
		ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);


		LOGGER.info("uri:"+requestWrapper.getRequestURI());
		LOGGER.info("clientIp:"+requestWrapper.getRemoteAddr());
		LOGGER.info("requestHeaders:"+ MAPPER.valueToTree(getRequestHeaders(requestWrapper)));
		
		try {
			super.doDispatch(requestWrapper, responseWrapper);
		} finally {
			String method = requestWrapper.getMethod();
			LOGGER.info("method:"+method);
			if (method.equals("GET")) {
				LOGGER.info(method+" request:"+ MAPPER.valueToTree(requestWrapper.getParameterMap()));
			} else {
				JsonNode newNode = MAPPER.readTree(requestWrapper.getContentAsByteArray());
				LOGGER.info(method+" request:"+newNode);
			}
			LOGGER.info("status:"+responseWrapper.getStatus());
			
			JsonNode newNode = MAPPER.readTree(responseWrapper.getContentAsByteArray());
			LOGGER.info("response:"+newNode);
			
			responseWrapper.copyBodyToResponse();
			LOGGER.info("responseHeaders:"+ MAPPER.valueToTree(getResponsetHeaders(responseWrapper)));
		}

	}

	private Map getRequestHeaders(HttpServletRequest request) {

		Map headers = new HashMap<>();

		Enumeration headerNames = request.getHeaderNames();

		while (headerNames.hasMoreElements()) {

			String headerName = (String)headerNames.nextElement();

			headers.put(headerName, request.getHeader(headerName));

		}

		return headers;

	}

	private Map getResponsetHeaders(ContentCachingResponseWrapper response) {
	
		Map headers = new HashMap<>();
		
		Collection headerNames = response.getHeaderNames();
		
		for (Object headerName : headerNames) {
		
			headers.put(headerName, response.getHeader((String)headerName));
		
		}
		
		return headers;
	
	}
}